package com.PrivtLTE.demo;

import com.PrivtLTE.QuickVision.*;
import com.PrivtLTE.demo.MainActivity.PlaceholderFragment;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;

import android.opengl.GLSurfaceView;
import android.util.Log;
import android.view.SurfaceView;
import android.view.View;

public class VideoCallActivity extends Activity {
	public static final String EXTRA_IP = "ip_addr";
	public static final String EXTRA_VIDEO_FORMAT = "video_format";
	public static final String EXTRA_BITRATE = "bitrate";
	public static final String EXTRA_AUDIO_SEND = "audio_send_format";
	public static final String EXTRA_AUDIO_RECEIVE = "audio_receive_format";
	
	private QuickVision mQV;
	private QVAudioDev mAudioDev;
	private QVAudioCodec mAudioCodec;
	private QVVideoEncoder mVideoEncoder;
	private QVVideoDecoder mVideoDecoder;
	private QVAudioChannel mAudioChannel;
	private QVVideoChannel mVideoChannel;
	private QVVideoCapture mVideoCapture;
	
	String mIpAddr;
	int mVideoFormat, mBitrate, mAudioSend, mAudioReceive;
	
	private GLSurfaceView mPreviewView;
	private SurfaceView mDecodedView;
	
	private VideoCallActivity mSelf;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.video_call);
		
		Intent intent = getIntent();
		
		mIpAddr = intent.getStringExtra(EXTRA_IP);
		mVideoFormat = intent.getIntExtra(EXTRA_VIDEO_FORMAT, 1);
		mBitrate = intent.getIntExtra(EXTRA_BITRATE, 2048000);
		mAudioSend = intent.getIntExtra(EXTRA_AUDIO_SEND, 2);
		mAudioReceive = intent.getIntExtra(EXTRA_AUDIO_RECEIVE, 2);
		
		mDecodedView = (SurfaceView) findViewById(R.id.decoded);
		mPreviewView = (GLSurfaceView) findViewById(R.id.preview);

		mPreviewView.setVisibility(View.VISIBLE);
		mVideoCapture = new QVVideoCapture(0, this, mPreviewView);
		
		if(Build.VERSION.SDK_INT < 19)
		    mPreviewView.bringToFront();
	}
	
	   @Override
	    protected void onResume() {
		   		   
	        super.onResume();
	        
	        mSelf = this;
	        
    		new Thread(new Runnable() {
				@Override
				public void run() {
					//Log.d("VideoCall", "run");
					
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
                    int width, height, bitrate;

    	            //Log.d("VideoCall", "Open Camera Format : " + mVideoFormat);

			        switch(mVideoFormat) {
			            case 0: // 1080P
			    	        width = 1920;
			    	        height = 1080;
			                // mVideoCapture.Start(1920, 1080, 30);
			                break;
			        
			            case 2: // VGA
			    	        width = 640;
			    	        height = 480;
			    	        // mVideoCapture.Start(640, 480, 30);
			    	        break;
			        
			            case 1: // 720P
			            default:
			    	        width = 1280;
			    	        height = 720;
			    	        // mVideoCapture.Start(1280, 720, 30);
			    	        break;    	
			        }
			
			        mVideoCapture.Start(width, height, 30);
			
			        // mPreviewView.setVisibility(View.VISIBLE);
					
			        mQV = QuickVision.getInstance(mSelf);
			        mQV.Init("d82711e24c0de83b722133769143caeb");
			
			        //Log.e("Call", "encoder width : " + width + "height : " + height + "bitrate : " + mBitrate);
			
			        mVideoEncoder = new QVVideoEncoder(height, width, 30, mBitrate, mVideoCapture.GetEGLContext());
			        mVideoEncoder.Start();
			        mVideoEncoder.setTextureId(mVideoCapture.GetTextureId());
			        mVideoEncoder.rotate(90);
			        mVideoCapture.registerFrameAvailListener(mVideoEncoder);
			
			        mVideoDecoder = new QVVideoDecoder(width, height, mBitrate, mDecodedView.getHolder().getSurface());
			        mVideoDecoder.Start();
						
			        QVFormat format = QVFormat.CreateVideoFormat("H264", width, height);

			        mVideoChannel = new QVVideoChannel(1);
			        mVideoChannel.SetSendCodec(format);
			        mVideoChannel.SetReceiveCodec(format);
			
			        mVideoChannel.InitialSendSocket(mIpAddr, 8000);
			        mVideoChannel.InitialReceiveSocket(8000);
			
			        QVStream.LinkStream(mVideoEncoder, mVideoChannel, QVStream.QV_UP_STREAM);
			        QVStream.LinkStream(mVideoDecoder, mVideoChannel, QVStream.QV_DOWN_STREAM);
			
			        mVideoChannel.StartReceive();
			        mVideoChannel.StartSend();
			        
			        //////////////////////////////////
			        mAudioDev = new QVAudioDev(mSelf);
			        mAudioDev.SetMode(QVAudioDev.QV_AUDIO_VOIP_MODE);
			        mAudioDev.StartPlayout(16000);
			        
			        mAudioCodec = new QVAudioCodec(0, 16000, 16000);
			        
			        QVFormat sendFormat = new QVFormat();
			        switch(mAudioSend) {
			        case 0: // PCMU
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "PCMU");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 160);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 0);
			        	break;
			        	
			        case 1: // PCMA
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "PCMA");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 160);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 8);
			        	
			        	break;
			        	
			        case 2: // ILBC
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "ILBC");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 13300);	
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 240);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 102);
			        	
			        	break;
			        	
			        case 3: // OPUS
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "OPUS");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 48000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 2);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 960);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 120);
			        	
			        	break;
			        	
			        case 4: // ISAC
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "ISAC");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 16000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 32000);
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 480);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 103);
			        	
			        	break;
			        	
			        case 5: // G722
			        	sendFormat.SetString(QVFormat.KEY_PLNAME, "G722");
			        	sendFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 16000);
			        	sendFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	sendFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	sendFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 320);
			        	sendFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 9);
			        	
			        	break;
			        	
			        }
			        
			        int result;
			        result = mAudioCodec.SetEncoderCodec(sendFormat);
			        
			        QVFormat receiveFormat = new QVFormat();
			        switch(mAudioReceive) {
			        case 0: // PCMU
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "PCMU");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 160);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 0);
			        	break;
			        	
			        case 1: // PCMA
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "PCMA");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 160);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 8);
			        	
			        	break;
			        	
			        case 2: // ILBC
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "ILBC");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 8000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 13300);	
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 240);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 102);
			        	
			        	break;
			        	
			        case 3: // OPUS
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "OPUS");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 48000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 2);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 960);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 120);
			        	
			        	break;
			        	
			        case 4: // ISAC
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "ISAC");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 16000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 32000);
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 480);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 103);
			        	
			        	break;
			        	
			        case 5: // G722
			        	receiveFormat.SetString(QVFormat.KEY_PLNAME, "G722");
			        	receiveFormat.SetInteger(QVFormat.KEY_SAMPLE_RATE, 16000);
			        	receiveFormat.SetInteger(QVFormat.KEY_CHANNEL_NUMBER, 1);
			        	receiveFormat.SetInteger(QVFormat.KEY_BIT_RATE, 64000);
			        	
			        	receiveFormat.SetInteger(QVFormat.KEY_PAC_SIZE, 320);
			        	receiveFormat.SetInteger(QVFormat.KEY_PAYLOAD_TYPE, 9);
			        	
			        	break;
			        	
			        }
			        
			        result = mAudioCodec.SetDecoderCodec(receiveFormat);
			        
			        QVStream.LinkStream(mAudioDev, mAudioCodec, QVStream.QV_BOTH_STREAM);
			        
			        mAudioDev.RegisterAudioCodec(mAudioCodec);
			        
			        mAudioChannel = new QVAudioChannel(0);
			        result = mAudioChannel.SetSendCodec(sendFormat);
			        
			        result = mAudioChannel.SetReceiveCodec(receiveFormat);
			        
			        mAudioChannel.InitialReceiveSocket(6000);
			        mAudioChannel.InitialSendSocket(mIpAddr, 6000);
			        
			        QVStream.LinkStream(mAudioCodec, mAudioChannel, QVStream.QV_BOTH_STREAM);
			        mAudioChannel.RegisterCodec(mAudioCodec);
			        
			        mAudioCodec.SetFECStatus(true);
			        mAudioChannel.SetREDStatus(true);
			        mAudioChannel.SetNACKStatus(true);
			        
			        mAudioChannel.StartReceive();
			        mAudioChannel.StartSend();
			        
			        mAudioCodec.StartDecoder();
			        mAudioCodec.StartEncoder();
			        
			        mAudioDev.StartCapture(16000);
		        
				}
			}).start();
	    }
	   
	    @Override
	    protected void onDestroy() {
	        
	        super.onDestroy();
	        
	        
	        mVideoChannel.StopReceive();
	        mVideoChannel.StopSend();
	        
	        mVideoDecoder.Stop();
	        mVideoEncoder.Stop();
	       
	        if(mVideoCapture != null)
	        	mVideoCapture.Stop();
	        
	        QVStream.UnlinkStream(mVideoDecoder, mVideoChannel, QVStream.QV_DOWN_STREAM);
	        QVStream.UnlinkStream(mVideoEncoder, mVideoChannel, QVStream.QV_UP_STREAM);
	        QVStream.UnlinkStream(mVideoCapture, mVideoEncoder, QVStream.QV_UP_STREAM);
	        
	        mVideoChannel.Cleanup();
	        
	        mAudioChannel.StopReceive();
	        mAudioChannel.StopSend();
	        
	        mAudioCodec.StopDecoder();
	        mAudioCodec.StopEncoder();
	        
	        mAudioDev.StopPlayout();
	        mAudioDev.StopCapture();
	        
	        QVStream.UnlinkStream(mAudioCodec, mAudioChannel, QVStream.QV_BOTH_STREAM);
	        QVStream.UnlinkStream(mAudioDev, mAudioCodec, QVStream.QV_BOTH_STREAM);
	        
	        mAudioChannel.Cleanup();
	        mAudioCodec.Cleanup();
	        
	    }
	
}
